package com.gymmsystem.GYMMSystem.service.impl;

import com.gymmsystem.GYMMSystem.dto.CourseReservationDTO;
import com.gymmsystem.GYMMSystem.entity.Course;
import com.gymmsystem.GYMMSystem.mapper.CourseMapper;
import com.gymmsystem.GYMMSystem.service.CourseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
@Slf4j
public class CourseServiceImpl implements CourseService {

    private final CourseMapper courseMapper;

    // 在CourseServiceImpl类中添加方法实现
    @Override
    public CourseReservationDTO getCourseReservationInfo(Long courseId) {
        try {
            // 获取课程基本信息
            Course course = courseMapper.selectByIdWithRunStatus(courseId);
            if (course == null) {
                throw new RuntimeException("课程不存在");
            }

            // 获取教练信息
            Map<String, Object> coachInfo = courseMapper.findCoachInfoByCourseId(courseId);

            // 构建DTO
            CourseReservationDTO dto = new CourseReservationDTO();

            // 设置课程信息
            dto.setCourseId(course.getCId());
            dto.setCourseName(course.getCName());
            dto.setCourseImage(course.getCImage());
            dto.setCourseTime(course.getCTime());
            dto.setCourseDuration(course.getCDuration());
            dto.setCourseGrade(course.getCGrade());
            dto.setCourseIntroduction(course.getCIntroduction());
            dto.setCourseCurrent(course.getCCurrent());
            dto.setCourseMax(course.getCMax());

            // 设置教练信息
            if (coachInfo != null) {
                dto.setCoachId((Long) coachInfo.get("id"));
                dto.setCoachName((String) coachInfo.get("name"));
                dto.setCoachPhone((String) coachInfo.get("phone"));
                dto.setCoachSpecialty((String) coachInfo.get("specialty"));
                dto.setCoachExperience((Integer) coachInfo.get("experience"));
                dto.setCoachImageUrl((String) coachInfo.get("image_url"));
            }

            // 设置预约状态
            boolean canReserve = checkCourseCapacity(courseId) &&
                    course.getCTime().isAfter(LocalDateTime.now());
            dto.setCanReserve(canReserve);
            dto.setReservationStatus(canReserve ? "可预约" : "不可预约");

            return dto;
        } catch (Exception e) {
            log.error("获取课程预约信息失败，课程ID: {}", courseId, e);
            throw new RuntimeException("获取课程信息失败: " + e.getMessage());
        }
    }

    // 获取当前可用的课程列表
    @Override
    public List<Course> getAvailableCourses() {
        return courseMapper.findAvailableCourses();
    }

    // 根据教练ID查询该教练的所有课程
    @Override
    public List<Course> getCoursesByCoachId(Long coachId) {
        return courseMapper.findCoursesByCoachId(coachId);
    }

    // 根据课程ID获取课程详情
    @Override
    public Course getCourseById(Long courseId) {
        return courseMapper.selectByIdWithRunStatus(courseId);
    }

    @Override
    public String getCourseGrade(Long courseId) {
        Course course = getCourseById(courseId);
        return course != null ? course.getCGrade() : "初级";
    }

    // 创建新课程
    @Override
    public boolean createCourse(Course course) {
        course.setCCreatedAt(LocalDateTime.now());
        return courseMapper.insert(course) > 0;
    }

    // 更新课程信息
    @Override
    public boolean updateCourse(Course course) {
        log.info("开始更新课程 - 课程ID: {}", course.getCId());
        try {
            // 验证课程ID是否存在
            Course existingCourse = courseMapper.selectById(course.getCId());
            if (existingCourse == null) {
                log.warn("更新课程失败 - 课程不存在，课程ID: {}", course.getCId());
                return false;
            }

            // 使用MyBatis-Plus的更新方法，只更新非空字段
            // 直接使用course对象，但设置c_run_status为null以避免非数据库字段问题
            course.setCRunStatus(null);

            // 执行更新
            int result = courseMapper.updateById(course);
            boolean success = result > 0;
            log.info("更新课程结果 - 课程ID: {}, 更新成功: {}, 影响行数: {}",
                    course.getCId(), success, result);
            return success;
        } catch (Exception e) {
            log.error("更新课程时发生异常 - 课程ID: {}", course.getCId(), e);
            throw new RuntimeException("更新课程失败: " + e.getMessage(), e);
        }
    }

    // 删除课程
    @Override
    public boolean deleteCourse(Long courseId) {
        return courseMapper.deleteById(courseId) > 0;
    }

    // 增加课程当前报名人数
    // 原子操作，将c_current字段加1
    // 确保不会超过课程最大人数限制
    // 使用场景：用户成功预约课程时调用
    @Override
    public boolean incrementCourseCurrent(Long courseId) {
        return courseMapper.incrementCurrentCount(courseId) > 0;
    }

    // 减少课程当前报名人数
    // 原子操作，将c_current字段减1
    // 确保人数不会减到负数
    // 使用场景：用户取消预约时调用
    @Override
    public boolean decrementCourseCurrent(Long courseId) {
        return courseMapper.decrementCurrentCount(courseId) > 0;
    }

    // 获取包含教练信息的课程列表
    // 关联查询课程表和教练表
    // 返回课程信息+教练姓名等详细信息
    // 使用场景：前端显示课程列表时需要显示教练信息
    @Override
    public List<Course> getCoursesWithCoachInfo() {
        return courseMapper.findCoursesWithCoachInfo();
    }

    // 检查教练在指定时间是否可用
    // 查询教练在指定时间是否已有课
    // 用于避免时间冲突
    // 使用场景：创建新课程前的时间冲突检查
    @Override
    public boolean checkCoachAvailability(Long coachId, String courseTime) {
        return courseMapper.countCoachCoursesAtTime(coachId, courseTime) == 0;
    }

    // 新增：检查课程容量
    // 检查课程是否还有空位
    // 比较当前人数和最大人数限制
    // 使用场景：用户预约课程前的容量检查
    @Override
    public boolean checkCourseCapacity(Long courseId) {
        try {
            Map<String, Object> capacity = courseMapper.getCourseCapacity(courseId);
            if (capacity == null) {
                log.warn("课程不存在或已下架，课程ID: {}", courseId);
                return false;
            }

            Integer maxCapacity = (Integer) capacity.get("c_max");
            Integer currentCount = (Integer) capacity.get("c_current");

            boolean hasCapacity = currentCount < maxCapacity;
            log.debug("课程容量检查 - 课程ID: {}, 最大容量: {}, 当前人数: {}, 是否还有空位: {}",
                    courseId, maxCapacity, currentCount, hasCapacity);

            return hasCapacity;
        } catch (Exception e) {
            log.error("检查课程容量失败，课程ID: {}", courseId, e);
            return false;
        }
    }

    // 获取课程图片URL
    @Override
    public String getCourseImageUrl(Long courseId) {
        try {
            return courseMapper.findCourseImageById(courseId);
        } catch (Exception e) {
            log.error("获取课程图片失败，课程ID: {}", courseId, e);
            return null;
        }
    }

    // 更新课程图片
    @Override
    public boolean updateCourseImage(Long courseId, String imageUrl) {
        try {
            return courseMapper.updateCourseImage(courseId, imageUrl) > 0;
        } catch (Exception e) {
            log.error("更新课程图片失败，课程ID: {}, 图片URL: {}", courseId, imageUrl, e);
            return false;
        }
    }

    // 更新课程状态（上架/下架）
    @Override
    public boolean updateCourseStatus(Long courseId, Integer status) {
        try {
            return courseMapper.updateCourseStatus(courseId, status) > 0;
        } catch (Exception e) {
            log.error("更新课程状态失败，课程ID: {}, 状态: {}", courseId, status, e);
            return false;
        }
    }

    // 上传课程图片
    @Override
    public String uploadCourseImage(MultipartFile file) throws Exception {
        // 检查文件是否为空
        if (file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        // 检查文件类型
        String contentType = file.getContentType();
        if (contentType == null || !contentType.startsWith("image/")) {
            throw new IllegalArgumentException("只支持图片文件上传");
        }

        // 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String extension = originalFilename != null ? originalFilename.substring(originalFilename.lastIndexOf(".")) : ".jpg";
        String filename = "course_" + System.currentTimeMillis() + extension;

        // 保存文件到本地（实际项目中可能需要保存到云存储）
        // 这里使用临时目录作为示例
        String uploadDir = System.getProperty("user.dir") + File.separator + "upload";
        File dir = new File(uploadDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        File dest = new File(uploadDir + File.separator + filename);
        file.transferTo(dest);

        // 返回可访问的图片URL
        // 这里返回相对路径，实际项目中需要根据部署情况返回正确的URL
        return "/upload/" + filename;
    }

    /**
     * 自动更新课程相关的预约状态
     * - 课程进行中：预约中 -> 已确认
     * - 课程已结束：已确认 -> 已完成
     */
    @Override
    @Transactional
    public void autoUpdateReservationStatusByCourse(Long courseId) {
        Course course = courseMapper.selectById(courseId);
        if (course == null) {
            log.warn("课程不存在，courseId: {}", courseId);
            return;
        }

        LocalDateTime now = LocalDateTime.now();
        LocalDateTime courseStartTime = course.getCTime();
        LocalDateTime courseEndTime = courseStartTime.plusMinutes(course.getCDuration());

        // 检查课程是否正在进行中（当前时间在课程开始和结束之间）
        if (now.isAfter(courseStartTime) && now.isBefore(courseEndTime)) {
            // 课程进行中：将预约中 -> 已确认
            int updatedCount = courseMapper.updateReservationStatusForCourse(
                    courseId, "预约中", "已确认");
            log.info("课程进行中，自动更新预约状态：{}条预约从'预约中'改为'已确认'", updatedCount);
        }
        // 检查课程是否已结束
        else if (now.isAfter(courseEndTime)) {
            // 课程已结束：将已确认 -> 已完成
            int updatedCount = courseMapper.updateReservationStatusForCourse(
                    courseId, "已确认", "已完成");
            log.info("课程已结束，自动更新预约状态：{}条预约从'已确认'改为'已完成'", updatedCount);
        }
    }

    /**
     * 批量更新所有课程的预约状态
     * 使用场景：定时任务调用
     */
    @Override
    @Transactional
    public void batchAutoUpdateReservationStatus() {
        List<Course> allCourses = courseMapper.selectList(null); // 获取所有课程
        int totalUpdated = 0;

        for (Course course : allCourses) {
            try {
                // 获取当前课程的预约更新数量
                int updated = updateReservationStatusForSingleCourse(course);
                totalUpdated += updated;
            } catch (Exception e) {
                log.error("更新课程预约状态失败，courseId: {}", course.getCId(), e);
            }
        }

        log.info("批量更新完成，共更新{}条预约状态", totalUpdated);
    }

    /**
     * 单个课程的预约状态更新逻辑
     */
    private int updateReservationStatusForSingleCourse(Course course) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime courseStartTime = course.getCTime();
        LocalDateTime courseEndTime = courseStartTime.plusMinutes(course.getCDuration());
        int updatedCount = 0;

        if (now.isAfter(courseStartTime) && now.isBefore(courseEndTime)) {
            // 课程进行中
            updatedCount = courseMapper.updateReservationStatusForCourse(
                    course.getCId(), "预约中", "已确认");
        } else if (now.isAfter(courseEndTime)) {
            // 课程已结束
            updatedCount = courseMapper.updateReservationStatusForCourse(
                    course.getCId(), "已确认", "已完成");
        }

        return updatedCount;
    }

    /**
     * 分页查询课程列表（管理员使用）
     */
    @Override
    public Map<String, Object> getCoursesByPage(Integer page, Integer size, Integer status, String search) {
        Map<String, Object> result = new HashMap<>();

        // 计算偏移量
        int offset = (page - 1) * size;

        List<Map<String, Object>> courses;
        Integer total;

        // 判断是否有搜索关键词
        if (search != null && !search.trim().isEmpty()) {
            // 执行带搜索的查询
            courses = courseMapper.findCoursesByPageStatusAndSearch(offset, size, status, search);
            total = courseMapper.getCourseTotalCountByStatusAndSearch(status, search);
        } else {
            // 执行普通的状态查询
            courses = courseMapper.findCoursesByPageAndStatus(offset, size, status);
            total = courseMapper.getCourseTotalCountByStatus(status);
        }

        // 计算总页数
        int totalPages = (int) Math.ceil((double) total / size);

        // 封装结果
        result.put("data", courses);
        result.put("total", total);
        result.put("page", page);
        result.put("size", size);
        result.put("totalPages", totalPages);

        return result;
    }

    /**
     * 获取所有课程（管理员使用）
     */
    @Override
    public List<Map<String, Object>> getAllCourses() {
        return courseMapper.findAllCourses();
    }
}